/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core/system/platform
// Copyright (c) 2014.  All Rights Reserved
//
// File:		AEWin32Processor.cpp
// Author:		Gianluca Belardelli
// Date:		04/04/2014
//
/////////////////////////////////////////////////////////////////////////
#include <AECore.h>

#ifndef AE_PLATFORM_WIN32
#pragma error "Piattaforma non supportata"
#endif

AEUINT32	AEProcessor::m_uiNumCPU = 0;
AECHAR		AEProcessor::m_cAffinityMask[MAX_PROCESSOR_SUPPORTED];

AEProcessor &AEProcessor::GetInstance( void )
{
	static AEProcessor sInstance;
	return sInstance;
}

AEProcessor::AEProcessor( void )
{
	SYSTEM_INFO sysinfo;

#ifdef AE_PLATFORM_X64
	GetSystemInfo( &sysinfo );
#else
	GetNativeSystemInfo( &sysinfo );
#endif

	m_uiNumCPU = sysinfo.dwNumberOfProcessors;

	memset( m_cAffinityMask, 0, MAX_PROCESSOR_SUPPORTED );
    //
    // Get the processor affinities for this process.
    //
    DWORD_PTR lpProcessAffinityMask;
    DWORD_PTR lpSystemAffinityMask;

    GetProcessAffinityMask( GetCurrentProcess(), &lpProcessAffinityMask, &lpSystemAffinityMask );

	// Make sure we can use all processors.
	if( lpSystemAffinityMask != lpProcessAffinityMask )
	{
		MessageBox( NULL,
			TEXT ( "The Smoke process has been restricted, so it cannot use all processors in the system." ),
			TEXT ( "Smoke startup warning" ),
			MB_OK );
	}

    for ( AEUINT32 i=0; lpProcessAffinityMask > 0; i++, lpProcessAffinityMask >>= 1 )
    {
        if ( lpProcessAffinityMask & 1 )
            m_cAffinityMask[i] = 1;
    }
}

AEUINT32 AEProcessor::GetNumCPUAvailableForProcess( void )
{
	AEUINT32 uiResult=0;

	for( AEUINT32 i=0; i<MAX_PROCESSOR_SUPPORTED; i++ )
		if(m_cAffinityMask[i])
			uiResult++;

	return uiResult;
}

AEUINT32 AEProcessor::AffinitizeThreadToProcessor( AEUINT32 uiProcessorNumber )
{
	AEASSERT( uiProcessorNumber <= m_uiNumCPU );

	if( m_cAffinityMask[uiProcessorNumber] > 0 )
	{
		int nRet = SetThreadIdealProcessor( GetCurrentThread(), uiProcessorNumber );

		if( nRet == -1 )
			return 1;

		return 0;
	}

	return 2;
}



AEUINT32 AEProcessor::GetNumCPU( void )
{
	return m_uiNumCPU;
}
